﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using legend;

namespace ryscanner
{
    public partial class Form1 : Form
    {

        private int pid = -1;
        private ScannerController ScannerController;
        private String lastScanType;

        private List<SearchAddressNumValue> lastSearchResults;
        public Form1()
        {
            InitializeComponent();
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }


        private void initList() {
            List<SearchAddressNumValue> list = this.lastSearchResults;
            List<SearchAddressNumValue> showList = new List<SearchAddressNumValue>();
            int l = list.Count > 10 ? 10 : list.Count;
            for (int li = 0; li < l; li++)
            {
                showList.Add(list[li]);
            }
            this.listView1.BeginUpdate();
            this.listView1.Items.Clear();
            foreach (var li in list) {
                ListViewItem listViewItem = new ListViewItem();
                listViewItem.Text = li.getAddress();
                if (li.isBaseAddr()) {
                    listViewItem.ForeColor = Color.Green;
                }
                listViewItem.SubItems.Add(li.getHexVal());
                listViewItem.SubItems.Add(li.getValue() + "");
                this.listView1.Items.Add(listViewItem);
            }
            this.listView1.EndUpdate();
            this.lastScanType = this.type;
        }

        private List<long> scanHex() {
            if (this.isBetween.Checked)
            {
                UInt32 v1 = Convert.ToUInt32(this.valueTextBox.Text, 16);
                UInt32 v2 = Convert.ToUInt32(this.valueBoxText2.Text, 16);
                UInt32 max = v1 > v2 ? v1 : v2;
                UInt32 min = max == v1 ? v2 : v1;
                return this.ScannerController.scanBetween(min, max);
            }
            else {
                UInt32 v1 = Convert.ToUInt32(this.valueTextBox.Text, 16);
                byte[] bytes = BitConverter.GetBytes(v1);
                return this.ScannerController.scanBytes(bytes);
            }
        }

        private List<long> scanStr() {
            byte[] bytes = Encoding.GetEncoding("gb2312").GetBytes(this.valueTextBox.Text);
            return this.ScannerController.scanBytes(bytes);
        }

        private List<long> scanShort() {
            string t = this.valueTextBox.Text;
            short v = short.Parse(t);
            byte[] feature = BitConverter.GetBytes(v);
            return this.ScannerController.scanBytes(feature);
        }


        private void button2_Click(object sender, EventArgs e)
        {

            try {

                List<long> ptrs = null;
                switch (this.type) {
                    case type_int16:
                        ptrs = this.scanShort();
                        break;
                    case type_hex:
                        ptrs = this.scanHex();
                        break;
                    case type_str:
                        ptrs = this.scanStr();
                        break;
                    default:
                        ptrs = this.scanShort();
                        break;
                }


                List<SearchAddressNumValue> list = new List<SearchAddressNumValue>();
                int l = 2;
                if (type_int16.Equals(this.type)) {
                    l = 2;
                }
                if (type_str.Equals(this.type)) {
                    l = 20;
                }
                if (type_hex.Equals(this.type))
                {
                    l = 4;
                }

                foreach (var ptr in ptrs) {
                    if (!this.ScannerController.isBaseAddr(ptr))
                    {
                        SearchAddressNumValue searchAddressNumValue = new SearchAddressNumValue(ptr, this.ScannerController.getBytes(ptr, l));
                        list.Add(searchAddressNumValue);
                    }
                    else {
                        SearchAddressNumValue searchAddressNumValue = new SearchAddressNumValue(ptr, this.ScannerController.getBytes(ptr, l), true);
                        list.Add(searchAddressNumValue);
                    }
                }

                this.lastSearchResults = list;
                this.initList();
                MessageBox.Show("扫描成功");

            } catch (Exception) {
                MessageBox.Show("失败");

            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            try
            {
                var v = Int16.Parse(this.valueTextBox.Text);
                List<SearchAddressNumValue> vs = new List<SearchAddressNumValue>();
                int l = 2;
                if (type_int16.Equals(this.lastScanType))
                {
                    l = 2;
                }
                if (type_str.Equals(this.lastScanType))
                {
                    l = 20;
                }
                if (type_hex.Equals(this.lastScanType))
                {
                    l = 4;
                }
                foreach (var lv in this.lastSearchResults) {
                    long address = lv.getLongAddr();
                    var readVal = BitConverter.ToInt16(this.ScannerController.getBytes(address, l));
                    if (readVal == v) {
                        vs.Add(lv);
                        lv.UpdateVal(BitConverter.GetBytes(readVal));
                    }
                }
                this.lastSearchResults = vs;
                this.initList();
                MessageBox.Show("扫描成功");
            }
            catch (Exception) {
                MessageBox.Show("失败");
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string tPid = this.pidTextBox.Text;
            try
            {
                this.pid = int.Parse(tPid);
                Process process = Process.GetProcessById(this.pid);
                this.ScannerController = new ScannerController(process);
                MessageBox.Show("设置成功");
            }
            catch (Exception) {
                MessageBox.Show("pid 设置失败");
            }

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            this.int16Radio.Checked = true;
        }

        private void button4_Click(object sender, EventArgs e)
        {
            foreach (var lv in this.lastSearchResults)
            {
                long address = lv.getLongAddr();
                lv.UpdateVal(this.ScannerController.getBytes(address, 2));
            }
            this.updateList();
        }

        private void updateList() {
            this.listView1.BeginUpdate();
            foreach (var li in this.lastSearchResults) {
                if (li.isChanged()) {
                    foreach (ListViewItem lvi in this.listView1.Items) {
                        if (li.getAddress().Equals(lvi.Text)) {
                            lvi.SubItems[1].Text = li.getHexVal();
                            lvi.SubItems[2].Text = li.getValue() + "";
                            lvi.BackColor = Color.Red;
                        }
                    }

                }
            }
            this.listView1.EndUpdate();
            MessageBox.Show("更新结束");
        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {

        }
        private const String type_hex = "hex";
        private const String type_int16 = "int16";
        private const String type_str = "str";
        private const String type_guess = "guess";

        private String type = type_int16;

        private void hexRadio_CheckedChanged(object sender, EventArgs e)
        {
            if (this.hexRadio.Checked) {
                this.type = type_hex;
            }
        }

        private void int16Radio_CheckedChanged(object sender, EventArgs e)
        {
            if (this.int16Radio.Checked) {

                this.type = type_int16;
            }
        }


        private void strRadio_CheckedChanged(object sender, EventArgs e)
        {
            if (this.strRadio.Checked) {
                this.type = type_str;
            }
        }


        private void button5_Click(object sender, EventArgs e)
        {
            try {
                UInt32 v1 = Convert.ToUInt32(this.valueTextBox.Text, 16);
                List<BaseAddress> addrs = this.ScannerController.baseAddressGuess(v1, 5, 1024);
                if (addrs != null && addrs.Count > 0)
                {
                    this.guessListView.BeginUpdate();
                    this.guessListView.Items.Clear();
                    foreach (var addr in addrs) {
                        ListViewItem item = new ListViewItem();
                        item.Text = addr.ptr.ToString("X8");
                        if (addr.baseAddr)
                        { item.ForeColor = Color.Green; }
                        item.SubItems.Add(addr.basePtr.ToString("X8"));
                        item.SubItems.Add(addr.offset + "");
                        this.guessListView.Items.Add(item);
                    }
                    this.guessListView.EndUpdate();
                    MessageBox.Show("猜完了。。。。");

                }
            } catch (Exception) {
                MessageBox.Show("失败了。。");
            }
        }

        private long showAddr;
        private long showOffset;



        private void showbtn_Click(object sender, EventArgs e)
        {
            try {
                long addr = Convert.ToUInt32(this.showAddrTextBox.Text, 16);
                long offset = int.Parse(this.offsetBox.Text);
                byte[] bytes = this.ScannerController.getBytes(addr + offset, 1024);
                this.showAddr = addr;
                this.showOffset = offset;
                this.memoryListView.BeginUpdate();
                this.memoryListView.Items.Clear();
                for (int r = 0; r < 64; r++) {
                    var rowBase = addr + (r * 16);
                    ListViewItem listViewItem = new ListViewItem();
                    listViewItem.Text = rowBase.ToString("X8");
                    for (int i = 0; i < 4; i++) {
                        UInt32 v = BitConverter.ToUInt32(bytes, r * 16 + i * 4);
                        listViewItem.SubItems.Add(v.ToString("X8"));
                    }
                    for (int i = 0; i < 8; i++)
                    {
                        UInt32 v = BitConverter.ToUInt16(bytes, r * 16 + i * 2);
                        listViewItem.SubItems.Add(v + "");
                    }
                    listViewItem.SubItems.Add(Encoding.GetEncoding("gb2312").GetString(bytes));
                    this.memoryListView.Items.Add(listViewItem);
                }
                this.memoryListView.EndUpdate();
                //if (!this.timer1.Enabled) {
                //    this.timer1.Enabled = true;
                //    this.timer1.Tick += Timer1_Tick;
                //    this.timer1.Interval = 1000;
                //    this.timer1.Start();
                //}

            } catch (Exception) {
                MessageBox.Show("看不见啊啊");
            }
        }

        private void Timer1_Tick(object sender, EventArgs e)
        {
            long addr = this.showAddr;
            long offset = this.showOffset;
            byte[] bytes = this.ScannerController.getBytes(addr + offset, 1024);
            this.showAddr = addr;
            this.showOffset = offset;
            this.memoryListView.BeginUpdate();
            for (int r = 0; r < 64; r++)
            {
                var rowBase = addr + (r * 16);
                ListViewItem listViewItem = this.memoryListView.Items[r];
                for (int i = 0; i < 4; i++)
                {
                    var oldV = listViewItem.SubItems[i + 1].Text;
                    UInt32 v = BitConverter.ToUInt32(bytes, r * 16 + i * 4);
                    var nV = v.ToString("X8");
                    listViewItem.SubItems[i + 1].Text = nV;
                    if (oldV.Equals(nV))
                    {
                        listViewItem.SubItems[i + 1].BackColor = Color.White;
                    }
                    else {
                        listViewItem.SubItems[i + 1].BackColor = Color.Red;
                    }
                }
                for (int i = 0; i < 8; i++)
                {
                    var oldV = listViewItem.SubItems[4 + i + 1].Text;
                    UInt32 v = BitConverter.ToUInt16(bytes, r * 16 + i * 2);
                    var nv = v + "";
                    listViewItem.SubItems[4 + i + 1].Text = nv;
                    if (oldV.Equals(nv))
                    {
                        listViewItem.SubItems[4 + i + 1].BackColor = Color.White;
                    }
                    else
                    {
                        listViewItem.SubItems[4 + i + 1].BackColor = Color.Red;
                    }
                }
                listViewItem.SubItems[13].Text = (Encoding.GetEncoding("gb2312").GetString(bytes));
            }
            this.memoryListView.EndUpdate();

        }

        private void button6_Click(object sender, EventArgs e)
        {
            this.Timer1_Tick(sender, e);
        }
        const long pkgItemName_offset = 0x00;
        const long pkgItem_attack_offset = 0x281;
        const long pkgItem_magic_offset = 0x289;
        const long pkgItem_daoshu_offset = 0x291;
        private bool testPt(long ptr) {
            if (!this.ScannerController.isBaseAddr(ptr)) {
                return false;
            }
            if (BitConverter.ToUInt16(this.ScannerController.getBytes(ptr + pkgItem_magic_offset, 2)) !=1) {
                return false;
            }
            if (BitConverter.ToUInt16(this.ScannerController.getBytes(ptr + pkgItem_attack_offset, 2)) !=16)
            {
                return false;
            }
            if (BitConverter.ToUInt16(this.ScannerController.getBytes(ptr + pkgItem_daoshu_offset, 2)) !=5)
            {
                return false;
            }
            return true;


        }

        public void predict(object sender, EventArgs e) {
            byte[] bytes = Encoding.GetEncoding("gb2312").GetBytes("无极棍");
            List<long> ptrs = this.ScannerController.scanBytes(bytes);
            foreach (var ptr in ptrs)
            {
                if (testPt(ptr))
                {
                    this.prediictLable.Text = ptr.ToString("X8");
                    this.timer1.Stop();
                    return;
                }
            }
            foreach (var ptr in ptrs)
            {
                UInt32 p = (UInt32)ptr;
                byte[] sbytes = BitConverter.GetBytes(p);
                List<long> ptts = this.ScannerController.scanBytes(sbytes);
                foreach (var pttr in ptts)
                {
                    if (testPt(pttr))
                    {
                        this.prediictLable.Text = ptr.ToString("X8");
                        this.timer1.Stop();
                        return;
                    }
                }
            }
        }

        private int st = 0;

        private void button7_Click(object sender, EventArgs e)
        {
            if (this.timer1.Enabled)
            {
                this.timer1.Stop();
            }
            else {
                this.timer1.Tick += predict;
                this.timer1.Interval = 1000;
                this.timer1.Start();
                this.prediictLable.Text = "searching..";
            }
        
        }

        private void button8_Click(object sender, EventArgs e)
        {
            List<SearchAddressNumValue> list = new List<SearchAddressNumValue>();
          
            this.type = type_hex;

            //foreach (var ptr in baseAddrs)
            //{
                    
            //        SearchAddressNumValue searchAddressNumValue = new SearchAddressNumValue(ptr, this.ScannerController.getBytes(ptr, 4), true);
            //        list.Add(searchAddressNumValue);
            //}
            this.lastSearchResults = list;
            this.initList();

        }
    }
}
